1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.apache.tapestry5.internal.services;
16
17 import java.math.BigDecimal;
18 import java.math.BigInteger;
19 import java.text.DecimalFormatSymbols;
20 import java.text.ParseException;
21 import java.util.Locale;
22 import java.util.Map;
23
24 import org.apache.tapestry5.Field;
25 import org.apache.tapestry5.Translator;
26 import org.apache.tapestry5.ValidationException;
27 import org.apache.tapestry5.internal.test.InternalBaseTestCase;
28 import org.apache.tapestry5.internal.translator.BigDecimalNumericFormatter;
29 import org.apache.tapestry5.internal.translator.BigIntegerNumericFormatter;
30 import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
31 import org.apache.tapestry5.ioc.services.ThreadLocale;
32 import org.apache.tapestry5.ioc.util.UnknownValueException;
33 import org.apache.tapestry5.services.TranslatorSource;
34 import org.testng.annotations.BeforeClass;
35 import org.testng.annotations.BeforeMethod;
36 import org.testng.annotations.DataProvider;
37 import org.testng.annotations.Test;
38
39 @SuppressWarnings("unchecked")
40 public class TranslatorSourceImplTest extends InternalBaseTestCase
41 {
42 private TranslatorSource source;
43
44 @BeforeClass
45 public void setup()
46 {
47 source = getService(TranslatorSource.class);
48 }
49
50 @BeforeMethod
51 public void setupThreadLocale()
52 {
53 getService(ThreadLocale.class).setLocale(Locale.ENGLISH);
54 }
55
56 @Test
57 public void found_translator_by_name()
58 {
59 Translator translator = mockTranslator("mock", String.class);
60
61 replay();
62
63 TranslatorSource source = new TranslatorSourceImpl(newConfiguration(String.class, translator));
64
65 assertSame(source.get("mock"), translator);
66
67 verify();
68 }
69
70 private Map<Class, Translator> newConfiguration(Class type, Translator t)
71 {
72 Map<Class, Translator> result = CollectionFactory.newMap();
73 result.put(type, t);
74
75 return result;
76 }
77
78 @Test
79 public void key_and_type_mismatch()
80 {
81 Translator t = mockTranslator();
82
83 train_getType(t, Long.class);
84
85 replay();
86
87 try
88 {
89 new TranslatorSourceImpl(newConfiguration(Integer.class, t));
90 unreachable();
91 }
92 catch (RuntimeException ex)
93 {
94 assertMessageContains(ex,
95 "Contributed translator for type java.lang.Integer reports its type as java.lang.Long.");
96 }
97
98 verify();
99 }
100
101 @Test
102 public void name_collision_with_standard_translators()
103 {
104 Translator t1 = mockTranslator("fred", Integer.class);
105 Translator t2 = mockTranslator("fred", Long.class);
106
107 Map<Class, Translator> configuration = CollectionFactory.newMap();
108 configuration.put(Integer.class, t1);
109 configuration.put(Long.class, t2);
110
111 replay();
112
113 try
114 {
115 new TranslatorSourceImpl(configuration);
116 unreachable();
117 }
118 catch (RuntimeException ex)
119 {
120 assertMessageContains(
121 ex,
122 "Two different Translators contributed to the TranslatorSource service use the same translator name: 'fred'.",
123 "Translator names must be unique.");
124 }
125
126 verify();
127 }
128
129 @Test
130 public void get_alternate_translator_by_name()
131 {
132 Translator t1 = mockTranslator("fred", Integer.class);
133 Translator t2 = mockTranslator();
134
135 Map<Class, Translator> configuration = newConfiguration(Integer.class, t1);
136
137 Map<String, Translator> alternates = CollectionFactory.newMap();
138 alternates.put("barney", t2);
139
140 replay();
141
142 TranslatorSource source = new TranslatorSourceImpl(configuration, alternates);
143
144 assertSame(source.get("barney"), t2);
145
146 verify();
147 }
148
149 @Test
150 public void name_collision_between_standard_and_alternate_translator()
151 {
152 Translator t1 = mockTranslator("fred", Integer.class);
153 Translator t2 = mockTranslator();
154
155 Map<Class, Translator> configuration = newConfiguration(Integer.class, t1);
156
157 Map<String, Translator> alternates = CollectionFactory.newMap();
158 alternates.put("fred", t2);
159
160 replay();
161
162 try
163 {
164 new TranslatorSourceImpl(configuration, alternates);
165 unreachable();
166 }
167 catch (RuntimeException ex)
168 {
169 assertEquals(
170 ex.getMessage(),
171 "Translator 'fred' contributed to the TranslatorAlternatesSource service has the same name as a standard Translator contributed to the TranslatorSource service.");
172 }
173
174 verify();
175 }
176
177 @Test
178 public void unknown_translator_is_failure()
179 {
180 Translator fred = mockTranslator("fred", String.class);
181 Translator barney = mockTranslator("barney", Long.class);
182
183 Map<Class, Translator> configuration = CollectionFactory.newMap();
184
185 configuration.put(String.class, fred);
186 configuration.put(Long.class, barney);
187
188 replay();
189
190 TranslatorSource source = new TranslatorSourceImpl(configuration);
191
192 try
193 {
194 source.get("wilma");
195 unreachable();
196 }
197 catch (UnknownValueException ex)
198 {
199 assertMessageContains(ex, "Unknown translator type 'wilma'.");
200 }
201 }
202
203 @DataProvider
204 public Object[][] to_client_data()
205 {
206 return new Object[][]
207 {
208
209 { Byte.class, (byte) 65, "65" },
210
211 { Integer.class, 997, "997" },
212
213 { Long.class, 12345l, "12345" },
214
215
216
217
218
219 { Double.class, 3.1428571429d, "3.143" },
220
221 { String.class, "abcd", "abcd" },
222
223 { Short.class, (short) 95, "95" },
224
225 { Float.class, (float) -22.7, "-22.7" },
226
227 { BigInteger.class, new BigInteger("123456789012345678901234567890"), "123456789012345678901234567890" },
228
229 { BigDecimal.class, new BigDecimal("-9876543219876543321987654321.12345123451234512345"),
230 "-9876543219876543321987654321.12345123451234512345" } };
231 }
232
233 @Test(dataProvider = "to_client_data")
234 public void to_client(Class type, Object value, String expected)
235 {
236 Translator t = source.getByType(type);
237
238 String actual = t.toClient(value);
239
240 assertEquals(actual, expected);
241 }
242
243 @DataProvider
244 public Object[][] parse_client_success_data()
245 {
246 return new Object[][]
247 {
248
249 { Byte.class, " 23 ", (byte) 23 },
250
251 { Short.class, " -121 ", (short) -121 },
252
253 { Integer.class, " 123 ", 123 },
254
255 { Integer.class, " 20,000 ", 20000 },
256
257 { Long.class, " -1234567 ", -1234567l },
258
259 { Double.class, "3.1428571429", 3.1428571429d },
260
261 { String.class, " abcdef ", " abcdef " },
262
263 { Float.class, " 28.95 ", (float) 28.95 },
264
265 { BigInteger.class, " -123456789012345678901234567890",
266 new BigInteger("-123456789012345678901234567890") },
267
268 { BigDecimal.class, "-9,876,543,219,876,543,321,987,654,321.12345123451234512345",
269 new BigDecimal("-9876543219876543321987654321.12345123451234512345") } };
270 }
271
272 @Test(dataProvider = "parse_client_success_data")
273 public void parse_client(Class type, String input, Object expected) throws Exception
274 {
275 Translator t = source.getByType(type);
276
277 Object actual = t.parseClient(null, input, null);
278
279 assertEquals(actual, expected);
280 }
281
282 @DataProvider
283 public Object[][] parse_client_failure_data()
284 {
285 String intError = "You must provide an integer value for Fred.";
286 String floatError = "You must provide a numeric value for Fred.";
287
288 return new Object[][]
289 {
290
291 { Byte.class, "fred", intError },
292
293 { Integer.class, "fred", intError },
294
295 { Long.class, "fred", intError },
296
297 { Double.class, "fred", floatError },
298
299 { Float.class, "fred", floatError },
300
301 { Short.class, "fred", intError } };
302 }
303
304 @Test(dataProvider = "parse_client_failure_data")
305 public void parse_client_failure(Class type, String input, String expectedMessage)
306 {
307 Translator t = source.getByType(type);
308 Field field = mockField();
309
310 replay();
311
312 try
313 {
314 t.parseClient(field, input, expectedMessage);
315 unreachable();
316 }
317 catch (ValidationException ex)
318 {
319 assertEquals(ex.getMessage(), expectedMessage);
320 }
321
322 verify();
323 }
324
325 @Test
326 public void find_by_type()
327 {
328 Translator t = mockTranslator("string", String.class);
329
330 replay();
331
332 TranslatorSource source = new TranslatorSourceImpl(newConfiguration(String.class, t));
333
334 assertSame(source.getByType(String.class), t);
335 assertSame(source.findByType(String.class), t);
336 assertNull(source.findByType(Integer.class));
337
338 verify();
339 }
340
341 @Test
342 public void get_by_type_not_found()
343 {
344 Translator string = mockTranslator("string", String.class);
345 Translator bool = mockTranslator("bool", Boolean.class);
346
347 Map<Class, Translator> configuration = CollectionFactory.newMap();
348 configuration.put(String.class, string);
349 configuration.put(Boolean.class, bool);
350
351 replay();
352
353 TranslatorSource source = new TranslatorSourceImpl(configuration);
354
355 try
356 {
357 source.getByType(Integer.class);
358 unreachable();
359 }
360 catch (IllegalArgumentException ex)
361 {
362 assertEquals(ex.getMessage(),
363 "No translator is defined for type java.lang.Integer. Registered types: java.lang.Boolean, java.lang.String.");
364 }
365
366 verify();
367 }
368
369 @Test
370 public void biginteger_with_localized_symbols() throws ParseException
371 {
372 DecimalFormatSymbols symbols = new DecimalFormatSymbols(Locale.ENGLISH);
373 symbols.setGroupingSeparator('_');
374 symbols.setMinusSign('*');
375
376 BigIntegerNumericFormatter f = new BigIntegerNumericFormatter(symbols);
377
378 BigInteger big = new BigInteger("-123456");
379
380 assertEquals(f.parse("*123_456"), big);
381
382 assertEquals(f.toClient(big), "*123456");
383 }
384
385 @Test
386 public void bigdecimal_with_localized_symbols() throws ParseException
387 {
388 DecimalFormatSymbols symbols = new DecimalFormatSymbols(Locale.ENGLISH);
389 symbols.setGroupingSeparator('_');
390 symbols.setMinusSign('*');
391 symbols.setDecimalSeparator('#');
392
393 BigDecimalNumericFormatter f = new BigDecimalNumericFormatter(symbols);
394
395 BigDecimal big = new BigDecimal("-123456.797956563434");
396
397 assertEquals(f.parse("*123_456#797956563434"), big);
398
399 assertEquals(f.toClient(big), "*123456#797956563434");
400 }
401
402 }